;#IfWinActive, ahk_class Notepad
#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
Process, Priority, , High
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.


; Increase the following value to make the mouse cursor move faster:
JoyMultiplier = 0.30

; Decrease the following value to require less joystick displacement-from-center
; to start moving the mouse.  However, you may need to calibrate your joystick
; -- ensuring it's properly centered -- to avoid cursor drift. A perfectly tight
; and centered joystick could use a value of 1:
JoyThreshold = 20

; Change the following to true to invert the Y-axis, which causes the mouse to
; move vertically in the direction opposite the stick:
InvertYAxis := false

; If your system has more than one joystick, increase this value to use a joystick
; other than the first:
JoystickNumber = 1


; END OF CONFIG SECTION -- Don't change anything below this point unless you want
; to alter the basic nature of the script.


#SingleInstance

; Setup the POV Switchable modes
Click_Mode  = 3
Camera_Mode = 2
Move_Mode   = 1
POV_Mode    = Move_Mode

; Setup the Trigger Modes
Trig_Up     = 1
Trig_Left   = 2
Trig_Right  = 3
Trig_Mode   = Trig_Up


JoystickPrefix = %JoystickNumber%Joy

; Calculate the axis displacements that are needed to start moving the cursor:
JoyThresholdUpper := 50 + JoyThreshold
JoyThresholdLower := 50 - JoyThreshold
if InvertYAxis
    YAxisMultiplier = -1
else
    YAxisMultiplier = 1

SetTimer, WatchJoystick, 10  ; Monitor the movement of the joystick.
SetTimer, WatchMouselook, 10 ; Monitor right stick
SetTimer, WatchPOV, 10       ; Monitor POV
SetTimer, WatchTriggers, 10  ; Monitor Triggers

; Simple button to key maps
ButtonA  = 1
ButtonB  = 2
ButtonX  = 3
ButtonY  = 4
ButtonLb = 5
ButtonRb = 6
ButtonBk = 7
ButtonSt = 8
ButtonLs = 9
ButtonRs = 10

Hotkey, %JoystickPrefix%%ButtonA%, ButtonA
Hotkey, %JoystickPrefix%%ButtonB%, ButtonB
Hotkey, %JoystickPrefix%%ButtonX%, ButtonX
Hotkey, %JoystickPrefix%%ButtonY%, ButtonY
Hotkey, %JoystickPrefix%%ButtonLb%, ButtonLb
Hotkey, %JoystickPrefix%%ButtonRb%, ButtonRb
Hotkey, %JoystickPrefix%%ButtonBk%, ButtonBk
Hotkey, %JoystickPrefix%%ButtonSt%, ButtonSt
Hotkey, %JoystickPrefix%%ButtonLs%, ButtonLs
Hotkey, %JoystickPrefix%%ButtonRs%, ButtonRs

return  ; End of auto-execute section.

ButtonA:
  if Trig_Mode = %Trig_Up%
    Send 3
  else if Trig_Mode = %Trig_Left%
    Send r
  else
    Send r
return

ButtonB:
  if Trig_Mode = %Trig_Up%
    Send t
  else if Trig_Mode = %Trig_Left%
    Send 2
  else
    Send 2
return

ButtonX:
  if Trig_Mode = %Trig_Up%
    Send b
  else if Trig_Mode = %Trig_Left%
    Send 0
  else
    Send 0
return

ButtonY:
  if Trig_Mode = %Trig_Up%
    Send g
  else if Trig_Mode = %Trig_Left%
    Send v
  else
    Send v
return

ButtonLb:
  if Trig_Mode = %Trig_Up%
    Send q
  else if Trig_Mode = %Trig_Left%
    Send 7
  else
    Send 7
return

ButtonRb:
  if Trig_Mode = %Trig_Up%
    Send c
  else if Trig_Mode = %Trig_Left%
    Send e
  else
    Send e
return

ButtonBk:
  POV_Mode = %Move_Mode%
  Send {escape}
return

ButtonSt:
  if Trig_Mode = %Trig_Up%
    Send f
  else if Trig_Mode = %Trig_Left%
    Send 8
  else
    Send 8
return

ButtonRs:
  if POV_Mode = %Click_Mode%
  {
    if Trig_Mode = %Trig_Up%
    {
      Click left
      POV_Mode = %Move_Mode%
    }
    else
    {
      Click right
      POV_Mode = %Move_Mode%
    }
  }
  else
  {
     if POV_Mode = %Camera_Mode%
       POV_Mode = %Move_Mode%
     else
       POV_Mode = %Camera_Mode%
  }
return
  

ButtonLs:
  if Trig_Mode = %Trig_Up%
    Send {space}
  else if Trig_Mode = %Trig_Left%
    Send {space}
  else
    Send {space}
return

WatchJoystick:
SetFormat, float, 03
GetKeyState, joyx, %JoystickNumber%JoyX
GetKeyState, joyy, %JoystickNumber%JoyY

KeyToHoldDownPrev = %KeyToHoldDown%  ; Prev now holds the key that was down before (if any).
YKeyToHoldDownPrev = %YKeyToHoldDown%  ; Prev now holds the key that was down before (if any).

if joyx > 70
    KeyToHoldDown = d
else if joyx < 30
    KeyToHoldDown = a
else
    KeyToHoldDown =

if joyy > 70
    YKeyToHoldDown = s
else if joyy < 30
    YKeyToHoldDown = w
else
    YKeyToHoldDown =

; Otherwise, release the previous key and press down the new key:
SetKeyDelay -1  ; Avoid delays between keystrokes.

if !(KeyToHoldDownPrev = KeyToHoldDown)
{
  if KeyToHoldDownPrev   ; There is a previous key to release.
   Send, {%KeyToHoldDownPrev% up}  ; Release it.
  if KeyToHoldDown   ; There is a key to press down.
   Send, {%KeyToHoldDown% down}  ; Press it down.
}

if !(YKeyToHoldDownPrev = YKeyToHoldDown)
{
  if YKeyToHoldDownPrev   ; There is a previous key to release.
   Send, {%YKeyToHoldDownPrev% up}  ; Release it.
  if YKeyToHoldDown   ; There is a key to press down.
   Send, {%YKeyToHoldDown% down}  ; Press it down.
}

return


WatchMouselook:
MLMouseNeedsToBeMoved := false  ; Set default.
SetFormat, float, 03
GetKeyState, joyu, %JoystickNumber%JoyU
GetKeyState, joyr, %JoystickNumber%JoyR

ClickDownPrev = %ClickDown%  ; Prev now holds the key that was down before (if any).

if joyu > %JoyThresholdUpper%
{
    MLMouseNeedsToBeMoved := true
    DeltaU := joyu - JoyThresholdUpper
}
else if joyu < %JoyThresholdLower%
{
    MLMouseNeedsToBeMoved := true
    DeltaU := joyu - JoyThresholdLower
}
else
    DeltaU := 0

if joyr > %JoyThresholdUpper%
{
    MLMouseNeedsToBeMoved := true
    DeltaR := joyr - JoyThresholdUpper
}
else if joyr < %JoyThresholdLower%
{
    MLMouseNeedsToBeMoved := true
    DeltaR := joyr - JoyThresholdLower
}
else
    DeltaR := 0

if MLMouseNeedsToBeMoved
{
    SetMouseDelay, -1 ; Makes movement smoother.
    
    ClickDown := true
    if !(ClickDownPrev = ClickDown)
    {
      if POV_Mode = %Move_Mode%
      {
        Click down right
      }
      else if POV_Mode = %Camera_Mode%
      {
        Click down left
      }
    }

    MouseMove, DeltaU * JoyMultiplier, DeltaR * JoyMultiplier * YAxisMultiplier, 0, R
}
else
{
    ClickDown := false
    if !(ClickDownPrev = ClickDown)
    {
      if POV_Mode = %Move_Mode%
      {
        Click up right
      }
      else if POV_Mode = %Camera_Mode%
      {
        Click up left
      }
    }
}
return


WatchTriggers:
SetFormat, float, 03
GetKeyState, joyz, %JoystickNumber%JoyZ

if joyz > %JoyThresholdUpper%
{
  Trig_Mode   = %Trig_Left%
}
else if joyz < %JoyThresholdLower%
{
  Trig_Mode   = %Trig_Right%
}
else
  Trig_Mode   = %Trig_Up%


return

WatchPOV:
GetKeyState, JoyPOV, %JoystickNumber%JoyPOV
if JoyPOV = -1  ; Do Nothing
    return
if JoyPOV = 27000 ; Target closest Enemy
    Send {tab}
else if JoyPOV = 18000  ; Move Mode
{
    POV_Mode = %Click_Mode%
}
else if JoyPOV = 4500  ; Camera Mode
{
    POV_Mode = %Move_Mode%
}
else if JoyPOV = 9000  ; Camera Mode
{
    POV_Mode = %Move_Mode%
}
else if JoyPOV = 0 ; Click Mode
{
    POV_Mode = %Move_Mode%
}
return
